# 引用 JSON 文件

Rslib 支持在代码中引用 JSON 文件，也支持引用 [YAML](https://yaml.org/) 和 [TOML](https://toml.io/cn/) 文件并将其转换为 JSON 格式。

## JSON 文件

你可以直接在 JavaScript 文件中引用 JSON 文件。

:::warning

在 bundle 模式下，JSON 文件支持默认引用和具名引用。

在 bundleless 模式下，JSON 文件仅支持具名引用。

:::

### 默认引用

```json title="example.json"
{
  "name": "foo",
  "items": [1, 2]
}
```

```js title="index.js"
import example from './example.json';

console.log(example.name); // 'foo';
console.log(example.items); // [1, 2];
```

### 具名引用

Rslib 同样支持通过 named import 来引用 JSON 文件。

下面是一个使用示例，假设源码如下：

import { Tabs, Tab } from '@theme';

<Tabs>
  <Tab label="src/index.ts">

```js
import { name } from './example.json';

console.log(name); // 'foo';
```

  </Tab>
  <Tab label="src/example.json">

```json
{
  "name": "foo",
  "items": [1, 2]
}
```

  </Tab>
</Tabs>

会根据配置文件中的 [产物结构](/guide/basic/output-structure) 配置，输出如下产物：

<Tabs>
<Tab label="bundle">
<Tabs>
  <Tab label="dist/index.js">
```tsx
var example_namespaceObject = {
  u: 'foo',
};
console.log(example_namespaceObject.u);
```

  </Tab>
</Tabs>
</Tab>

<Tab label="bundleless">

<Tabs>
  <Tab label="dist/index.js">

```tsx
import * as example from './example.js';

console.log(example.name);
```

  </Tab>
  <Tab label="dist/example.js">
```tsx
var example_namespaceObject = JSON.parse('{"name":"foo","items":[1,2]}');
var __webpack_exports__items = example_namespaceObject.items;
var __webpack_exports__name = example_namespaceObject.name;
export { __webpack_exports__items as items, __webpack_exports__name as name };
```
  </Tab>
</Tabs>
</Tab>

</Tabs>

### 使用 import attributes

在 bundle 模式下，Rslib 支持 [import attributes](https://github.com/tc39/proposal-import-attributes)，你可以通过 import attributes 来引入 JSON 文件：

```js title="index.js"
import json from './example.json' with { type: 'json' };
```

在 bundleless 模式下，通过 import attributes 引入 JSON 文件时，需要确保产物中保留对 JSON 文件的引用，参考 [文档](#bundleless) 进行配置。

## YAML 文件

[YAML](https://yaml.org/) 是一种数据序列化语言，通常用于编写配置文件。

通过添加 [@rsbuild/plugin-yaml](https://github.com/rspack-contrib/rsbuild-plugin-yaml) 插件，你可以在 JavaScript 中引用 `.yaml` 或 `.yml` 文件，它们会被自动转换为 JavaScript 对象。

import { PackageManagerTabs } from '@theme';

<PackageManagerTabs command="add @rsbuild/plugin-yaml -D" />

### 注册插件

你可以在 `rslib.config.ts` 文件中注册插件：

```ts title="rslib.config.ts"
import { pluginYaml } from '@rsbuild/plugin-yaml';

export default {
  plugins: [pluginYaml()],
};
```

### 示例

<Tabs>
  <Tab label="src/index.ts">

```ts
import example from './example.yaml';

console.log(example.hello); // 'world';
console.log(example.foo); // { bar: 'baz' };
```

</Tab>
<Tab label="src/example.yaml">

```yaml
hello: world
foo:
  bar: baz
```

  </Tab>
</Tabs>

## TOML 文件

[TOML](https://toml.io/cn/) 是一种语义明显、易于阅读的配置文件格式。

通过添加 [@rsbuild/plugin-toml](https://github.com/rspack-contrib/rsbuild-plugin-toml) 插件，你可以在 JavaScript 中引用 `.toml` 文件，它们会被自动转换为 JavaScript 对象。

<PackageManagerTabs command="add @rsbuild/plugin-toml -D" />

### 注册插件

你可以在 `rslib.config.ts` 文件中注册插件：

```ts title="rslib.config.ts"
import { pluginToml } from '@rsbuild/plugin-toml';

export default {
  plugins: [pluginToml()],
};
```

### 示例

<Tabs>
  <Tab label="src/index.ts">

```ts
import example from './example.toml';

console.log(example.hello); // 'world';
console.log(example.foo); // { bar: 'baz' };
```

  </Tab>
  <Tab label="src/example.toml">

```toml
hello = "world"

[foo]
bar = "baz"
```

  </Tab>
</Tabs>

## 类型声明

当你在 TypeScript 代码中引用 YAML 或 TOML 文件时，请在项目中创建 `src/env.d.ts` 文件，并添加相应的类型声明。

- 方法一：如果项目里安装了 `@rslib/core` 包，你可以直接引用 `@rslib/core` 提供的 [预设类型](/guide/basic/typescript#预设类型)：

```ts title="src/env.d.ts"
/// <reference types="@rslib/core/types" />
```

- 方法二：手动添加需要的类型声明：

```ts title="src/env.d.ts"
declare module '*.yaml' {
  const content: Record<string, any>;
  export default content;
}
declare module '*.yml' {
  const content: Record<string, any>;
  export default content;
}
declare module '*.toml' {
  const content: Record<string, any>;
  export default content;
}
```

## 打包模式与输出

Rslib 支持在不同的打包模式下，JSON / YAML / TOML 文件以不同的形式输出。

### bundle

在 bundle 模式下（即 [`bundle: true`](/config/lib/bundle)），JSON 文件会被直接打包到 JavaScript 产物中，且 JSON 文件中没有被使用到的 key 会被 tree-shake 掉，TOML 和 YAML 文件同理。

### bundleless

在 bundleless 模式下（即 [`bundle: false`](/config/lib/bundle)），每个 JSON / YAML / TOML 文件会被转换为对应的 JavaScript 模块输出，JSON 文件会被转换为 `JSON.parse` 的形式并导出，YAML 和 TOML 文件会被转换为 JavaScript 对象并导出。

如果希望 JSON / YAML / TOML 文件按原样输出到产物目录，并且产物 JavaScript 文件中保留对这些文件的引用路径，可以通过以下方式完成：

1. 在 [source.entry](/config/rsbuild/source#sourceentry) 入口文件的 glob 匹配中忽略 JSON / YAML / TOML 文件
2. 在 [output.externals](/config/rsbuild/output#outputexternals) 中保留 JSON / YAML / TOML 文件的请求路径
3. 在产物输出中添加 [output.copy](/config/rsbuild/output#outputcopy) 选项，指定 JSON / YAML / TOML 文件的输出路径

例如下面的配置将会将 `src` 目录下的所有 JSON 文件按原样输出：

```ts title="rslib.config.ts"
export default defineConfig({
  lib: [
    {
      bundle: false,
      source: {
        entry: {
          index: ['./src/**', '!./src/**/*.json'], // [!code highlight]
        },
      },
      output: {
        // [!code highlight:2]
        copy: [{ from: './**/*.json', context: './src' }],
        externals: [/.*\.json$/],
      },
    },
  ],
});
```
